<?php

namespace app\worker\controller\kefu;

use ba\Date;
use think\App;
use Throwable;
use think\facade\Db;
use GatewayWorker\Lib\Gateway;
use app\admin\model\kefu\User;
use app\worker\library\WorkerWsApp;
use app\worker\library\kefu\Common;
use modules\kefu\library\StrComparison;

/**
 * 客服 WebSocket Mixed 控制器
 */
class WsMixed
{
    /**
     * 客服系统配置
     */
    protected array $config = [];

    /**
     * 构造方法
     * @param WorkerWsApp $app 应用对象
     * @throws Throwable
     */
    public function __construct(protected App $app)
    {
        $configData = Db::name('kefu_config')->select();
        foreach ($configData as $item) {
            $this->config[$item['name']] = $item['value'];
        }

        $this->app->lang->load([
            app_path() . 'lang' . DIRECTORY_SEPARATOR . 'date.php',
        ]);
    }

    public function ping(): void
    {
        $this->app->send('pong', []);
    }

    /**
     * 修改用户基本信息（包括游客）
     * @throws Throwable
     */
    public function changeUserBaseInfo(): void
    {
        $kfUser = Common::getUser();
        if ($kfUser['identity'] != 'csr') {
            $this->app->send('error', [
                'message' => '您没有权限修改用户资料！',
                'code'    => 500,
            ]);
            return;
        }

        $id        = $this->app->message['id'] ?? 0;
        $value     = $this->app->message['value'] ?? '';
        $field     = $this->app->message['field'] ?? '';
        $sessionId = $this->app->message['sessionId'] ?? 0;
        if (!$id || !$field) {
            $this->app->send('error', [
                'message' => '参数错误！',
                'code'    => 500,
            ]);
            return;
        }

        if ($field == 'user_id' && $value) {
            $user = User::where('user_id', $value)
                ->where('id', '<>', $id)
                ->find();
            if ($user) {
                $this->app->send('error', [
                    'message' => '该会员已经绑定了其他账户！',
                    'code'    => 500,
                ]);

                // 通知修改无效，重置表单
                if ($sessionId) {
                    $this->app->send('operates', [
                        'sessionId' => $sessionId,
                        'operate'   => 'refreshSessionInfo'
                    ]);
                } else {
                    $this->app->send('operates', [
                        'id'      => $id,
                        'operate' => 'refreshTouristInfo'
                    ]);
                }
                return;
            }
        }

        $user         = User::find($id);
        $user->$field = $value;

        // 绑定会员改变时，重新设定用户身份
        if ($field == 'user_id') {
            if ($value && $user->identity == 'tourist') {
                $user->identity = 'user';
            }
            if (!$value && $user->identity == 'user') {
                $user->identity = 'tourist';
            }
        }

        $user->save();

        // 获取新的用户信息
        if ($field == 'nickname' || $field == 'user_id') {
            $value = User::find($id);
            $value = User::outputFields(['avatar', 'nickname'], $value);
        }

        if ($sessionId) {
            // 发给当前客服代表
            $this->app->send('changeUserBaseInfo', [
                'id'        => $id,
                'value'     => $value,
                'field'     => $field,
                'sessionId' => $sessionId,
            ]);
        } else {
            // 游客资料修改 - 发给所有客服代表
            Gateway::sendToGroup(Common::mark('csrGroup'), $this->app->assembleMessage('changeUserBaseInfo', [
                'id'    => $id,
                'value' => $value,
                'field' => $field,
            ]));
        }
    }

    /**
     * 游客信息
     * @throws Throwable
     */
    public function touristInfo(): void
    {
        $id      = $this->app->message['id'] ?? 0;
        $tourist = User::find($id);
        if (!$tourist) {
            $this->app->send('error', [
                'message' => '游客找不到啦！',
                'code'    => 500,
            ]);
            return;
        }

        $this->app->send('touristInfo', [
            'touristInfo' => $tourist,
        ]);
    }

    /**
     * 记录轨迹
     */
    public function trajectory(): void
    {
        Common::getSession($this->app->clientId);

        $title     = $this->app->message['title'] ?? '';
        $details   = $this->app->message['details'] ?? '';
        $url       = $this->app->message['url'] ?? '';
        $referrer  = $this->app->message['referrer'] ?? '';
        $broadcast = $this->app->message['broadcast'] ?? false;

        $insertData = [
            'user_id'     => Common::getUser('id'),
            'title'       => $title,
            'details'     => $details,
            'url'         => $url,
            'referrer'    => $referrer,
            'create_time' => time(),
        ];
        Db::name('kefu_trajectory')->insert($insertData);

        // 广播访客轨迹
        if ($broadcast) {
            Gateway::sendToGroup(Common::mark('csrGroup'), $this->app->assembleMessage('tourists', ['action' => 'trajectory'] + $insertData));
        }
    }

    /**
     * 客服代表获取轨迹 tab 数据
     * @throws Throwable
     */
    public function getTrajectoryData(): void
    {
        $id        = $this->app->message['id'] ?? 0;
        $page      = $this->app->message['page'] ?? 1;
        $size      = $this->app->message['size'] ?? 15;
        $sessionId = $this->app->message['sessionId'] ?? 0;

        $res = Db::name('kefu_trajectory')
            ->where('user_id', $id)
            ->order('create_time', 'desc')
            ->paginate([
                'page'      => $page,
                'list_rows' => $size,
            ])
            ->each(function ($item) {
                $item['create_time'] = Date::human($item['create_time']);
                return $item;
            });

        $this->app->send('trajectoryData', [
            'id'        => $id,
            'page'      => $page,
            'list'      => $res->items(),
            'nextPage'  => count($res->items()) == $size,
            'sessionId' => $sessionId,
        ]);
    }

    /**
     * 客服代表获取知识库 tab 数据
     * @throws Throwable
     */
    public function getKbsData(): void
    {
        $keywords = $this->app->message['keywords'] ?? '';

        $kbs = Db::name('kefu_kbs')
            ->where('status', 1)
            ->order('weigh', 'desc')
            ->select();

        $data          = [];
        $strComparison = new StrComparison();
        foreach ($kbs as $kb) {
            $problems = explode("\n", trim(str_replace("\r\n", "\n", $kb['problem'])));
            foreach ($problems as $problem) {
                $problem = trim($problem);
                $match   = $strComparison->getSimilar($keywords, $problem);
                if ($match > 0 && $match >= $kb['match']) {
                    $kb['match'] = $match;
                    $kb['title'] = $problem;
                    $data[]      = $kb;
                    break;
                }
            }
        }

        $this->app->send('kbsData', [
            'list'     => $data,
            'keywords' => $keywords,
        ]);
    }

    /**
     * 消息输入状态
     */
    public function messageInputState(): void
    {
        $state               = $this->app->message['state'] ?? '';
        $sessionId           = $this->app->message['sessionId'] ?? 0;
        $sessionUserId       = $this->app->message['sessionUserId'] ?? 0;
        $sessionUserIdentity = $this->app->message['sessionUserIdentity'] ?? 0;

        if ($sessionId && $sessionUserId) {
            $this->app->send('messageInputState', [
                'state'         => $state,
                'sessionId'     => $sessionId,
                'sessionUserId' => $sessionUserId,
            ], Common::mark('uid', [
                'id'       => $sessionUserId,
                'identity' => $sessionUserIdentity,
            ]));
        }
    }
}